//创建一个对象,里面存储所有的游戏数据及游戏方法
const game = {
  data: [], //定义一个数组，用来存所有的游戏的数据
  score: 0, //定义一个分数的属性
  gamerunning: 1, //定义一个游戏运行的状态，将其设置为1与其他状态区分开
  gameover: 0, //定义一个游戏结束的状态
  status: 0, //这个是目前游戏的状态，时刻的跟上面两个状态做比较，确定游戏处于运行或者结束
  start() {
    //游戏开始时候的方法
    //  游戏开始的时候肯定是要把游戏的状态设置成游戏运行的状态
    //  this == game
    this.status = this.gamerunning
    //  游戏开始的时候分数清空
    this.score = 0
    //  数组中的所有元素全部设置成0
    this.data = [
      [0, 0, 0, 0],
      [0, 0, 0, 0],
      [0, 0, 0, 0],
      [0, 0, 0, 0],
    ]
    this.randomNum() //调用下面自定义的随机函数，可以在移动和开始的时候随机出来一个数
    this.randomNum() //调用两次是因为这是游戏开始时的方法，开局随机出现两个数和位置，因此需要调用两次
    this.dataView() //调用下面所写的更新视图的方法
  },
  // 随机数的函数，开始的时候随机生成，移动的时候随机生成
  randomNum() {
    while (true) {
      //  随机生成行和列 0 - 3随机整数
      const r = Math.floor(Math.random() * 4) //随机生成一个行
      const c = Math.floor(Math.random() * 4) //随机生成一个列
      // 如果是空，则生成随机数
      if (this.data[r][c] === 0) {
        const num = Math.random() > 0.5 ? 2 : 4 //随机出现2或4
        this.data[r][c] = num
        // 生成后退出循环
        break
      }
    }
  },
  // 更新试图的方法
  dataView() {
    //  大的循环,然后把所有的元素全部遍历一遍
    for (let r = 0; r < 4; r++) {
      for (let c = 0; c < 4; c++) {
        // 找到对应的div
        const div = document.getElementById(`c${r}${c}`) // 字符串拼接
        // 如果数值为非空
        if (this.data[r][c] !== 0) {
          // 数组中对应的内容放到格子上面去
          div.innerHTML = this.data[r][c]
          // 样式也写成对应的
          div.className = `cell n${this.data[r][c]}`
        } else {
          // 为空的情况
          div.innerHTML = ''
          div.className = 'cell'
        }
      }
    }
    //  更新分数
    document.getElementById('score01').innerHTML = this.score
    //游戏没有结束的时候 弹出层时刻都是隐藏的
    if (this.status === this.gamerunning) {
      document.getElementById('gameover').style.display = 'none'
    } else {
      document.getElementById('gameover').style.display = 'block'
      document.getElementById('score02').innerHTML = this.score
    }
  },
  // 判断游戏是否结束的方法
  isgameover() {
    for (let r = 0; r < 4; r++) {
      for (let c = 0; c < 4; c++) {
        // 里面有空格子的时候，游戏还是可以运行
        if (this.data[r][c] === 0) {
          return false //表示游戏还没有结束
        }
        // 判断左右是否有相同的
        if (c < 3) {
          if (this.data[r][c] === this.data[r][c + 1]) {
            return false
          }
        }
        if (r < 3) {
          if (this.data[r][c] === this.data[r + 1][c]) {
            return false
          }
        }
      }
    }
    return true
  },

  // 左 右 上 下
  // 左移的方法
  moveLeft() {
    const before = String(this.data) //之前做一次转换
    //  具体的移动需要处理的逻辑，直接处理好每一行即可
    for (let r = 0; r < 4; r++) {
      this.moveLeftInRow(r)
    }
    const after = String(this.data) //移动之后再做一次转换
    //  如果说移动之前不等于移动之后,肯定是发生了移动
    if (before !== after) {
      this.randomNum() //生成随机数
      //   生成的随机数可能会造成游戏的 gameover
      if (this.isgameover()) {
        // 改变游戏的状态
        this.status = this.gameover
      }
      // 更新视图
      this.dataView()
    }
  },
  moveLeftInRow(r) {
    //只去做处理每一行的逻辑
    for (let c = 0; c < 3; c++) {
      const nextc = this.getNextinRow(r, c)
      if (nextc !== -1) {
        //  如果等于0,直接替换
        if (this.data[r][c] === 0) {
          this.data[r][c] = this.data[r][nextc]
          this.data[r][nextc] = 0 //位置恢复成0
          c-- //要让位置恢复到原地
        } else if (this.data[r][c] == this.data[r][nextc]) {
          this.data[r][c] *= 2 //位置直接翻一倍
          this.data[r][nextc] = 0
          this.score += this.data[r][c] //更新分数
        }
      } else {
        //没有找到
        break //直接退出循环
      }
    }
  },
  getNextinRow(r, c) {
    for (let i = c + 1; i < 4; i++) {
      if (this.data[r][i] !== 0) {
        return i //表示已经找到位置，并且把位置返回出来
      }
    }
    return -1 //返回一个标识符
  },
  // 右移的方法
  moveRight() {
    const before = String(this.data)
    for (let r = 0; r < 4; r++) {
      this.moveRightInRow(r)
    }
    const after = String(this.data)
    if (before !== after) {
      this.randomNum()
      if (this.isgameover()) {
        this.status = this.gameover
      }
      this.dataView()
    }
  },
  moveRightInRow(r) {
    for (let c = 4; c > 0; c--) {
      const prevc = this.getPrevInRow(r, c)
      if (prevc !== -1) {
        if (this.data[r][c] === 0) {
          this.data[r][c] = this.data[r][prevc]
          this.data[r][prevc] = 0
          c++
        } else if (this.data[r][c] === this.data[r][prevc]) {
          this.data[r][c] *= 2
          this.data[r][prevc] = 0
          this.score += this.data[r][c]
        }
      } else {
        break
      }
    }
  },
  getPrevInRow(r, c) {
    for (let i = c - 1; i >= 0; i--) {
      if (this.data[r][i] != 0) {
        return i
      }
    }
    return -1
  },
  // 上移
  moveUp() {
    const before = String(this.data)
    for (let c = 0; c < 4; c++) {
      this.moveUpInCol(c)
    }
    const after = String(this.data)
    if (before !== after) {
      this.randomNum()
      if (this.isgameover()) {
        this.status = this.gameover
      }
      this.dataView()
    }
  },
  moveUpInCol(c) {
    for (let r = 0; r < 4; r++) {
      const nextr = this.getNextInCol(r, c)
      if (nextr !== -1) {
        if (this.data[r][c] === 0) {
          this.data[r][c] = this.data[nextr][c]
          this.data[nextr][c] = 0
          r--
        } else if (this.data[r][c] === this.data[nextr][c]) {
          this.data[r][c] *= 2
          this.data[nextr][c] = 0
          this.score += this.data[r][c]
        }
      } else {
        break
      }
    }
  },
  getNextInCol(r, c) {
    for (let i = r + 1; i < 4; i++) {
      if (this.data[i][c] != 0) {
        return i
      }
    }
    return -1
  },
  // 下移的方法
  moveDown() {
    const before = String(this.data)
    for (let c = 0; c < 4; c++) {
      this.moveDownInCol(c)
    }
    const after = String(this.data)
    if (before !== after) {
      this.randomNum()
      if (this.isgameover()) {
        this.status = this.gameover
      }
      this.dataView()
    }
  },
  moveDownInCol(c) {
    for (let r = 3; r > 0; r--) {
      const prev = this.getPrevIncol(r, c)
      if (prev !== -1) {
        if (this.data[r][c] === 0) {
          this.data[r][c] = this.data[prev][c]
          this.data[prev][c] = 0
          r--
        } else if (this.data[r][c] === this.data[prev][c]) {
          this.data[r][c] *= 2
          this.data[prev][c] = 0
          this.score += this.data[r][c]
        }
      } else {
        break
      }
    }
  },
  getPrevIncol(r, c) {
    for (let i = r - 1; i >= 0; i--) {
      if (this.data[i][c] != 0) {
        return i
      }
    }
    return -1
  },
}

game.start()
console.log(game.data)
console.log(game.status)
console.log(game.score)
//键盘事件
document.onkeydown = function (event) {
  if (event.keyCode === 37) {
    //console.log("左")
    game.moveLeft()
  } else if (event.keyCode === 38) {
    //console.log("上")
    game.moveUp()
  } else if (event.keyCode === 39) {
    //console.log("右")
    game.moveRight()
  } else if (event.keyCode === 40) {
    //console.log("下")
    game.moveDown()
  }
}
//touch事件
//手指按下
let startX //设定开始起始位置的x坐标
let startY //设定开始起始位置的y坐标
let endX //设定结束滑动位置的x坐标
let endY //设定结束滑动位置的y坐标
document.addEventListener('touchstart', function (event) {
  // console.log("手指按下了屏幕")
  console.log(event)
  startX = event.touches[0].pageX
  startY = event.touches[0].pageY
})
//手指移动
//document.addEventListener('touchmove',function(){
// console.log("手指的移动")
//})
//手指松开
document.addEventListener('touchend', function (event) {
  // console.log("手指松开")
  console.log(event)
  endX = event.changedTouches[0].pageX //如何获取结束时的位置x
  endY = event.changedTouches[0].pageY
  const X = endX - startX
  const Y = endY - startY
  const absX = Math.abs(X) > Math.abs(Y)
  const absY = Math.abs(Y) > Math.abs(X)
  if (X > 0 && absX) {
    console.log('右滑动')
    game.moveRight()
  } else if (X < 0 && absX) {
    console.log('左滑动')
    game.moveLeft()
  }
  if (Y > 0 && absY) {
    console.log('下滑动')
    game.moveDown()
  }
  if (Y < 0 && absY) {
    console.log('上滑动')
    game.moveUp()
  }
})

document.querySelector('.startbtn').addEventListener('click', () => {
  game.start()
})
